//package suanzi.core.db.aspect;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import io.swagger.annotations.ApiOperation;
//import org.apache.commons.lang3.StringUtils;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.annotation.*;
//import org.aspectj.lang.reflect.CodeSignature;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.scheduling.annotation.EnableAsync;
//import org.springframework.stereotype.Component;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//
//import javax.servlet.http.HttpServletRequest;
//import java.lang.reflect.Method;
//import java.util.*;
//
///**
// * @Description: aop获取操作日志记录
// * @Version: 1.0
// */
//
//@Aspect
//@EnableAsync
//@Component
//public class HttpAspect {
//
//    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
//
//    private static ThreadLocal<Map<String, String>> threadLocalMap = new ThreadLocal<>();
//
//    @Value("${spring.application.name}")
//    private String APPLICATION_NAME ;
//
//    @Pointcut("execution(public * suanzi.core.db.controller.*.*(..)) ")
//    public void log() {
//    }
//
//    /**
//     * 功能描述: 用@Before标识的方法为前置方法，在目标方法的执行之前执行，即在连接点之前进行执行。
//     *
//     */
//    @Before("log()")
//    public void doBefore(JoinPoint joinPoint) {
//
//        try {
//            Map<String, String> map = new HashMap<>();
//            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//            HttpServletRequest request = attributes.getRequest();
//            String url = request.getRequestURL().toString(); //url
//            String methodType = request.getMethod(); //method
//            String ip = request.getRemoteAddr(); //ip
//            String className = joinPoint.getSignature().getDeclaringTypeName(); //类
//            String methodName = joinPoint.getSignature().getName(); //方法
//            List<Object> args = Arrays.asList(joinPoint.getArgs()); //类参数
//            ObjectMapper mapper = new ObjectMapper();
//            String inParams;
//            try {
//                inParams= mapper.writeValueAsString(args) ;
//            } catch (Exception e){
//                inParams="参数序列化异常,文件参数";
//            }
//            //获取参数类型列表
//            Class[] parameterTypes = ((CodeSignature)joinPoint.getSignature()).getParameterTypes();
//            //根据类名，方法名，方法参数类型获取方法注解
//            String methodDesc = getAnnotation(className, methodName, parameterTypes, "value");
//            //获取操作的用户名，如果是登录操作，直接从参数中获取
//            String username = "";
//
//            map.put("url", url);
//            map.put("serviceName", this.APPLICATION_NAME);
//            map.put("username", username);
//            map.put("ip", ip);
//            map.put("className", className);
//            map.put("methodName", methodName);
//            map.put("methodType", methodType);
//            map.put("methodDesc", methodDesc);
//            //inParams字段进行截断，数据库中是1000，这里截取900
//            inParams = getStringByLength(inParams,900);
//            map.put("inParams", inParams);
//            map.put("startTime", System.currentTimeMillis()+"");
//            //把获取的参数放到map
//            threadLocalMap.set(map);
//            logger.info("doBefore()，URL:"+ url + " ,用户名：" + username + " ,HTTP请求方法：" + methodType + ",IP：" + ip +  ",类名：" + className + ",方法：" + methodName + ",方法描述：" + methodDesc + ",参数为：" + args);
//        } catch (Exception e) {
////            e.printStackTrace();
//            logger.error("拦截前错误:" + e.getMessage());
//        }
//    }
//
//    /**
//     * 功能描述: 后置方法在连接点方法完成之后执行，无论连接点方法执行成功还是出现异常，都将执行后置方法。
//     */
//    @After("log()")
//    public void doAfter(JoinPoint point) {
////        String methodName = point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName();
////        List<Object> outArgs = Arrays.asList(point.getArgs());
////        logger.info("doAfter()，方法：" + methodName + ",参数：" + outArgs);
//    }
//
//    /**
//     * 功能描述: 当连接点方法成功执行后，返回通知方法才会执行，如果连接点方法出现异常，则返回通知方法不执行
//     */
//    @AfterReturning(returning = "object", pointcut = "log()")
//    public void doAfterReturning(JoinPoint point,Object object) {
//        ObjectMapper mapper = new ObjectMapper();
//        String outParams = "";
//        try {
//            outParams = mapper.writeValueAsString(object) ;
//        } catch (Exception e) {
//            logger.error(e.getMessage());
//        }
//        //outParams，数据库中是1000，这里截取900
//        outParams = getStringByLength(outParams,900);
//        Map<String, String> map = threadLocalMap.get();
//        map.put("outParams",outParams);
//        long costTime = System.currentTimeMillis() - Long.parseLong(map.get("startTime"));
//        map.put("costTime", costTime + "");
//        threadLocalMap.remove();
//        threadLocalMap.set(map);
//
////        Set keys = threadLocalMap.get().keySet();
////        for (Object key : keys) {
////            System.out.println(key + "=" +map.get(key));
////        }
//    }
//
//    /**
//     * 功能描述: 异常通知方法只在连接点方法出现异常后才会执行，否则不执行
//     *          通过throwing属性指定连接点方法出现异常信息存储在ex变量中，在异常通知方法中就可以从ex变量中获取异常信息了
//     */
//    @AfterThrowing(value = "log()", throwing="ex")
//    public void afterReturning(JoinPoint point, Exception ex){
//        String methodName = point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName();
//        List<Object> args = Arrays.asList(point.getArgs());
//        logger.info("doAfterThrowing()，方法：" + methodName + ",参数：" + args + ",异常：" + ex);
//        Map<String, String> map = threadLocalMap.get();
//        map.put("outParams",ex + "");
//        long costTime = System.currentTimeMillis() - Long.parseLong(map.get("startTime"));
//        map.put("costTime", costTime + "");
//        threadLocalMap.remove();
//        threadLocalMap.set(map);
////        Set keys = threadLocalMap.get().keySet();
////        for (Object key : keys) {
////            System.out.println(key + " : "+map.get(key));
////        }
//    }
//
//    /**
//     * 根据类名、方法名、方法类型获取该方法上指定注解参数的内容
//     * @param className 类名
//     * @param methodName 方法名
//     * @param parameterTypes 方法参数 Class数组
//     * @param annotationMethodName 要返回注解中的值的名称
//     * @return
//     */
//    private static String  getAnnotation(String className, String methodName, Class<?>[] parameterTypes, String annotationMethodName) {
//        String value = "";
//        try {
//            Class c = Class.forName(className);
//            Method[] methods = c.getDeclaredMethods();
//            Method method = c.getMethod(methodName, parameterTypes);
//            if(methods != null){
//                ApiOperation annotation = method.getAnnotation(ApiOperation.class);
//                if(annotation != null) {
//                    Method meth = annotation.annotationType().getMethod(annotationMethodName);
//                    if ( meth != null) {
//                        value = (String) meth.invoke(annotation, null);
//                    }
//                }
//            }
//        } catch (Exception e) {
//            logger.error(e.getMessage());
//        }
//        return value;
//    }
//
//    /**
//     * 根据长度截取字符串，避免入库的时候字段超长
//     * @param str
//     * @param length
//     * @return
//     */
//    private static String getStringByLength(String str, Integer length) {
//        //inParams字段进行截断，数据库中是1000，这里截取900
//        if (StringUtils.isNotBlank(str) && str.length() > length) {
//            int len = str.length();
//            str = str.substring(0, (length/2)-3) + "..."+ str.substring(len-(length/2), len);
//        }
//        return str;
//    }
//}
//
